import numpy as np
import matplotlib.pyplot as plt


class Perceptron:
    def __init__(self, learning_rate=0.1, num_iterations=100):
        self.learning_rate = learning_rate
        self.num_iterations = num_iterations

    def fit(self, X, y):
        # 初始化权重和偏置
        self.weights = np.zeros(X.shape[1])
        self.bias = 0

        # 迭代训练
        for i in range(self.num_iterations):
            for j in range(X.shape[0]):
                # 计算准则函数
                net_input = np.dot(X[j], self.weights) + self.bias
                y_pred = self.activation(net_input)

                # 更新权重和偏置
                self.weights += self.learning_rate * (y[j] - y_pred) * X[j]
                self.bias += self.learning_rate * (y[j] - y_pred)

    def predict(self, X):
        # 预测结果
        net_input = np.dot(X, self.weights) + self.bias
        y_pred = np.where(net_input >= 0, 1, -1)
        return y_pred

    def activation(self, net_input):
        # 激活函数
        return np.where(net_input >= 0, 1, -1)


# 样本空间W1中的点
X1 = np.array([[2, 1], [1, 2], [3, -3], [2, -1], [4, -2]])
y1 = np.ones(X1.shape[0])

# 样本空间W2中的点
X2 = np.array([[-2, 0.5], [-4, -1], [-1.5, -2.5], [-3, 1], [-1, 3], [-2, 2.5]])
y2 = -np.ones(X2.shape[0])

# 合并样本空间
X = np.vstack((X1, X2))
y = np.concatenate((y1, y2))

# 训练模型
model = Perceptron()
model.fit(X, y)

# 绘制散点图
plt.scatter(X1[:, 0], X1[:, 1], color='red', label='W1')
plt.scatter(X2[:, 0], X2[:, 1], color='blue', label='W2')

# 绘制决策边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01),
                     np.arange(y_min, y_max, 0.01))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
            linestyles=['--', '-', '--'])
# 待分类样本
sample = [(1,-2), (0,5), (-1,3.5), (2.5,3.5), (-2,4), (2,-3), (-4.5,-1), (0,1), (-2.5,1), (-1,-0.5)]

# 预测样本类别
for point in sample:
    if model.predict(np.array(point)) == 1:
        print(f"Point {point} belongs to W1.")
    else:
        print(f"Point {point} belongs to W2.")

# 添加标题和坐标轴标签
plt.title('Sample Spaces')
plt.xlabel('x')
plt.ylabel('y')

# 显示图像
plt.show()






